﻿using GoPlay.Models;
using GoPlay.Controllers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.SessionState;
//using GoPlay.Tests.Models;

namespace GoPlay.Tests.Controllers
{
    [TestClass]
    public class PlayersControllerTests
    {
        //[TestMethod]
        //public void Player_Index_GET_AsksForIndexView()
        //{
        //    // Arrange
        //    var controller = GetPlayersController(new InMemoryRepository<Player>());

        //    // Act
        //    ViewResult result = controller.Index() as ViewResult;

        //    // Assert
        //    Assert.AreNotEqual(null, result);
        //}

        //[TestMethod]
        //public void Player_Index_GET_RetrievesAllPlayersFromRepositoryForThisUser()
        //{
        //    // Arrange
        //    Player t = new Player { Name = "test", UserId = 1 };
        //    InMemoryRepository<Player> repository = new InMemoryRepository<Player>();
        //    repository.Insert(t);
        //    t = new Player { Name = "test2", UserId = 2 };
        //    repository.Insert(t);
        //    var controller = GetPlayersController(repository);

        //    // Act
        //    ViewResult result = controller.Index() as ViewResult;

        //    // Assert
        //    var model = (IEnumerable<Player>)result.Model;
        //    //CollectionAssert.Contains(model.ToList(), t);
        //    Assert.AreEqual(model.Count(), 1);
        //    Assert.AreEqual("test", model.First().Name);
        //}

        [TestMethod]
        public void Player_Create_POST_PutsValidPlayerIntoRepository()
        {
            // Arrange
            InMemoryRepository<Player> repository = new InMemoryRepository<Player>();
            PlayersController controller = GetPlayersController(repository);
            Player player = new Player { Id = 1, UserId = 1, TeamId = 1, ContactId=1, Goals=1, Assists=2, Points=3  };

            // Act
            controller.Create(player);

            // Assert
            IEnumerable<Player> Players = repository.GetAllByUserId(1);
            Assert.IsTrue(Players.Contains(player));
        }

        [TestMethod]
        public void Player_Create_POST_ReturnsRedirectOnSuccess()
        {
            // Arrange
            PlayersController controller = GetPlayersController(new InMemoryRepository<Player>());
            Player player = new Player { Id = 1, UserId = 1, TeamId = 1, ContactId = 1, Goals = 1, Assists = 2, Points = 3 };

            // Act
            var result = (RedirectToRouteResult)controller.Create(player);

            // Assert
            Assert.AreEqual("Details", result.RouteValues["action"]);
        }

        [TestMethod]
        public void Player_Create_POST_ReturnsViewIfModelStateIsNotValid()
        {
            // Arrange
            PlayersController controller = GetPlayersController(new InMemoryRepository<Player>());
            // Simply executing a method during a unit test does just that - executes a method, and no more. 
            // The MVC pipeline doesn't run, so binding and validation don't run.
            controller.ModelState.AddModelError("", "mock error message");
            Player player = new Player { Id = 1, UserId = 1, TeamId = 1, ContactId = 1, Goals = 1, Assists = 2, Points = 3 };

            // Act
            var result = (ViewResult)controller.Create(player);

            // Assert
            Assert.AreEqual("GoPlay.Models.Player", result.ViewData.Model.ToString());
        }

        [TestMethod]
        public void Player_Create_POST_ReturnsViewIfRepositoryThrowsException()
        {
            // Arrange
            InMemoryRepository<Player> repository = new InMemoryRepository<Player>();
            Exception exception = new Exception();
            repository.ExceptionToThrow = exception;
            PlayersController controller = GetPlayersController(repository);
            Player player = new Player { Id = 1, UserId = 1, TeamId = 1, ContactId = 1, Goals = 1, Assists = 2, Points = 3 };

            // Act
            var result = controller.Create(player) as ViewResult;

            // Assert
            ModelState modelState = result.ViewData.ModelState[""];
            Assert.IsNotNull(modelState);
            Assert.IsTrue(modelState.Errors.Any());
            Assert.AreEqual(exception, modelState.Errors[0].Exception);
        }

        [TestMethod]
        public void Player_Edit_POST_UpdatesPlayerInRepository()
        {
            //// Arrange
            //InMemoryRepository<Player> repository = new InMemoryRepository<Player>();
            //PlayersController controller = GetPlayersController(repository);
            //Player Player = new Player { Name = "test", UserId = 1 };

            //// Act
            //controller.Create(Player);

            //// Assert
            //IEnumerable<Player> Players = repository.GetAllPlayersForUser(1);
            //Assert.IsTrue(Players.Contains(Player));
            Assert.Inconclusive();
        }

        [TestMethod]
        public void Player_Edit_POST_ReturnsRedirectOnSuccess()
        {
            //// Arrange
            //PlayersController controller = GetPlayersController(new InMemoryRepository<Player>());
            //Player Player = new Player { Name = "test", UserId = 1 };

            //// Act
            //var result = (RedirectToRouteResult)controller.Create(Player);

            //// Assert
            //Assert.AreEqual("Index", result.RouteValues["action"]);
            Assert.Inconclusive();
        }

        [TestMethod]
        public void Player_Edit_POST_ReturnsViewIfModelStateIsNotValid()
        {
            //// Arrange
            //PlayersController controller = GetPlayersController(new InMemoryRepository<Player>());
            //// Simply executing a method during a unit test does just that - executes a method, and no more. 
            //// The MVC pipeline doesn't run, so binding and validation don't run.
            //controller.ModelState.AddModelError("", "mock error message");
            //Player Player = new Player { Name = "test", UserId = 1 };

            //// Act
            //var result = (ViewResult)controller.Create(Player);

            //// Assert
            //Assert.AreEqual("GoPlay.Models.Player", result.ViewData.Model.ToString());
            Assert.Inconclusive();
        }

        [TestMethod]
        public void Player_Edit_POST_ReturnsViewIfRepositoryThrowsException()
        {
            //// Arrange
            //InMemoryRepository<Player> repository = new InMemoryRepository<Player>();
            //Exception exception = new Exception();
            //repository.ExceptionToThrow = exception;
            //PlayersController controller = GetPlayersController(repository);
            //Player Player = new Player { Name = "test", UserId = 1 };

            //// Act
            //var result = (ViewResult)controller.Create(Player);

            //// Assert
            //ModelState modelState = result.ViewData.ModelState[""];
            //Assert.IsNotNull(modelState);
            //Assert.IsTrue(modelState.Errors.Any());
            //Assert.AreEqual(exception, modelState.Errors[0].Exception);
            Assert.Inconclusive();
        }



        private static PlayersController GetPlayersController(IRepository<Player> repository)
        {
            PlayersController controller = new PlayersController(repository);

            var sessionItems = new SessionStateItemCollection();
            sessionItems["UserId"] = "1";
            sessionItems["UserName"] = "chipirek";
            controller.ControllerContext = new MvcFakes.FakeControllerContext(controller, sessionItems);
            return controller;
        }

    }
}
